//  [9/13/2013 OMEGA] created


#include <QAbstractItemModel>
#include "DuelAssECommon.h"
#include "DuelAssEProject.h"
#include "DuelAssETranslator.h"
#include "DuelAssEGroupModel.h"
#include "DuelAssEGroupView.h"


DAssEGroupModelItem::DAssEGroupModelItem( DAssEGroupModelItem* parent /*= NULL*/ ) : 
	parentItem(parent)
{
}

DAssEGroupModelItem::~DAssEGroupModelItem()
{
	qDeleteAll(childItems);
}

DAssEGroupModelItem* DAssEGroupModelItem::child( int row )
{
	if (row < childItems.size() && row >= 0)
	{
		return childItems.at(row);
	}
	return NULL;
}

int DAssEGroupModelItem::childCount()
{
	return childItems.size();
}

bool DAssEGroupModelItem::insertChildren( int position, int count )
{
	if (position < 0 || position > childItems.size())
	{
		return false;
	}
	for (int row = 0; row < count; ++row)
	{
		DAssEGroupModelItem *item = new DAssEGroupModelItem(this);
		childItems.insert(position, item);
	}

	return true;
}

bool DAssEGroupModelItem::removeChildren( int position, int count )
{
	if (position < 0 || position + count > childItems.size())
	{
		return false;
	}

	for (int row = 0; row < count; ++row)
	{
		delete childItems.takeAt(position);
	}
	return true;
}

int DAssEGroupModelItem::indexOf( DAssEGroupModelItem* child )
{
	int idx = 0;
	QList<DAssEGroupModelItem*>::iterator i, iend =childItems.end();
	for (i = childItems.begin(); i != iend; ++i, ++idx)
	{
		if ((*i) == child)
		{
			return idx;
		}
	}
	return -1;
}

DAssEGroupModel::DAssEGroupModel( DAssEGroupView* parent ) : mParent(parent)
{
	mRootItem = new DAssEGroupModelItem();
	mRootItem->type = DAssEGroupModelItem::GMIT_ROOT;
}

DAssEGroupModel::~DAssEGroupModel()
{
	// clean up all children
	delete mRootItem;
}

void DAssEGroupModel::reset( DAssEProject* proj )
{
	clearItems();
	if (proj == NULL)
	{
		return;
	}
	GroupList* grpList = proj->getGroups();
	foreach(DAssEGroup* grp, *grpList)
	{
		addGroup(grp);
		ArchiveList* archList = grp->getAttachededArchives();
		foreach(DAssEArchive* arch, *archList)
		{
			attachArchiveToGroup(grp, arch);
		}
	}
}

QModelIndex DAssEGroupModel::index( int row, int column, const QModelIndex &parent /*= QModelIndex( ) */ ) const
{

	if (parent.isValid() && parent.column() != 0)
	{
		return QModelIndex();
	}
	DAssEGroupModelItem *parentItem = getItem(parent);

	DAssEGroupModelItem *childItem = parentItem->child(row);
	if (childItem)
	{
		return createIndex(row, column, childItem);
	}
	else
	{
		return QModelIndex();
	}
}

QModelIndex DAssEGroupModel::parent( const QModelIndex &child ) const
{
	if (!child.isValid())
	{
		return QModelIndex();
	}
	DAssEGroupModelItem* childItem = getItem(child);
	DAssEGroupModelItem* parentItem = childItem->parentItem;
	if (parentItem == mRootItem || parentItem == NULL)
	{
		return QModelIndex();
	}
	return createIndex(parentItem->childCount(), 0, parentItem);
}

int DAssEGroupModel::rowCount( const QModelIndex &parent /*= QModelIndex( ) */ ) const
{
	DAssEGroupModelItem *parentItem = getItem(parent);

	return parentItem->childCount();
}

int DAssEGroupModel::columnCount( const QModelIndex &parent /*= QModelIndex( ) */ ) const
{
	return 1;
}

Qt::ItemFlags DAssEGroupModel::flags( const QModelIndex &index ) const
{
	DAssEGroupModelItem* itm = getItem(index);
	if (itm->type == DAssEGroupModelItem::GMIT_GROUP)
	{
		return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
	}
	else if (itm->type == DAssEGroupModelItem::GMIT_ATTACHED_ARCHIVE)
	{
		return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
	}
	return Qt::ItemIsEnabled;
}

QVariant DAssEGroupModel::data( const QModelIndex &index, int role /*= Qt::DisplayRole */ ) const
{
	if (!index.isValid())
		return QVariant();

	if (role != Qt::DisplayRole && role != Qt::EditRole)
		return QVariant();

	DAssEGroupModelItem *item = getItem(index);

	return item->itemName;
}

QVariant DAssEGroupModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
	if (role != Qt::DisplayRole)
		return QVariant();

// 	if (orientation == Qt::Horizontal) {
// 		switch (section) {
// 		case 0:
// 			return tr("Group");
// 		default:
// 			return QVariant();
// 		}
// 	}

	return QVariant();
}

bool DAssEGroupModel::setData( const QModelIndex &idx, const QVariant &value, int role /*= Qt::EditRole*/ )
{
	DAssEGroupModelItem* itm = getItem(idx);
	
	itm->itemName = value.toString();

	emit dataChanged(idx, idx);
	return true;
}

bool DAssEGroupModel::insertRows( int position, int rows, const QModelIndex &parent /*= QModelIndex()*/ )
{
	DAssEGroupModelItem* parentItm = getItem(parent);
	beginInsertRows(parent, position, position + rows - 1);
	bool ok = parentItm->insertChildren(position, rows);
	endInsertRows();
	return ok;
}

bool DAssEGroupModel::removeRows( int position, int rows, const QModelIndex &parent /*= QModelIndex()*/ )
{
	DAssEGroupModelItem* parentItm = getItem(parent);
	beginRemoveRows(parent, position, position + rows - 1);
	bool ok = parentItm->removeChildren(position, rows);
	endRemoveRows();
	return ok;
}

DAssEGroupModelItem* DAssEGroupModel::getItem( const QModelIndex& index ) const
{
	if (index.isValid())
	{
		DAssEGroupModelItem *item = static_cast<DAssEGroupModelItem*>(index.internalPointer());
		if (item)
		{
			if (exist(item, mRootItem))
			{
				return item;
			}
		} 
	}
	return mRootItem;
}


bool DAssEGroupModel::exist( DAssEGroupModelItem* itm, DAssEGroupModelItem* parentItm ) const
{
	if (itm == parentItm)
	{
		return true;
	}
	bool bExist = false;
	QList<DAssEGroupModelItem*>::iterator i, iend = parentItm->childItems.end();
	for (i = parentItm->childItems.begin(); i != iend; ++i)
	{
		bExist = exist(itm, (*i));
		if (bExist)
		{
			return true;
		}
	}
	return false;
}

QModelIndex DAssEGroupModel::addGroup( DAssEGroup* grp )
{
	if (grp == NULL)
	{
		return QModelIndex();
	}
	int i = mRootItem->childCount();
	QModelIndex childIdx;
	bool result = insertRow(i);
	//idx = index()
	if (result)
	{ 
		childIdx = index(i, 0);
		setData(childIdx, grp->getName());
		DAssEGroupModelItem* itm = getItem(childIdx);
		itm->type = DAssEGroupModelItem::GMIT_GROUP;
	}
	return childIdx;
}

void DAssEGroupModel::removeGroup( DAssEGroup* grp )
{
	QList<DAssEGroupModelItem*>::iterator i, iend = mRootItem->childItems.end();
	int j = 0;
	for ( i = mRootItem->childItems.begin(); i != iend; ++i, ++j)
	{
		if ((*i)->itemName == grp->getName())
		{
			removeRow(j);
			return;
		}
	}
}

void DAssEGroupModel::renameGroup( const QString& oldGrpName, const QString& newGrpName )
{
	int idx = 0;
	QList<DAssEGroupModelItem*>::iterator i, iend = mRootItem->childItems.end();
	for (i = mRootItem->childItems.begin(); i != iend; ++i, ++idx)
	{
		if ((*i)->itemName == oldGrpName)
		{
			setData(index(idx, 0), newGrpName);
			return;
		}
	}
}

void DAssEGroupModel::clearItems()
{
	if (mRootItem->childCount() == 0)
	{
		return;
	}
	removeRows(0, mRootItem->childCount());
}

void DAssEGroupModel::attachArchiveToGroup( DAssEGroup* grp, DAssEArchive* arch )
{
	QList<DAssEGroupModelItem*>::iterator i, iend = mRootItem->childItems.end();
	int j = 0;
	for ( i = mRootItem->childItems.begin(); i != iend; ++i, ++j)
	{
		if ((*i)->itemName == grp->getName())
		{
			QModelIndex parentIdx = index(j,0);
			int childRow = (*i)->childCount();
			QModelIndex idx = index(childRow, 0, parentIdx);
			bool result = insertRow(childRow, parentIdx);
			if (result)
			{
				idx = index(childRow,0, parentIdx);
				setData(idx, arch->getName());
				DAssEGroupModelItem* itm = getItem(idx);
				itm->type = DAssEGroupModelItem::GMIT_ATTACHED_ARCHIVE;
			}
			return;
		}
	}
}

void DAssEGroupModel::detachArchiveFromGroup( DAssEGroup* grp, DAssEArchive* arch )
{
	QList<DAssEGroupModelItem*>::iterator gi, iend = mRootItem->childItems.end();
	int parentRow = 0;
	for (gi = mRootItem->childItems.begin(); gi != iend; ++gi, ++parentRow)
	{
		if ((*gi)->itemName == grp->getName())
		{
			DAssEGroupModelItem* groupItm = (*gi);
			QModelIndex parentIdx = index(parentRow, 0);
			for (int i = 0; i < groupItm->childCount(); ++i)
			{
				if (groupItm->child(i)->itemName == arch->getName())
				{
					removeRow(i, parentIdx);
					return;
				}
			}
		}
	}
}

QModelIndex DAssEGroupModel::getGroupIndex( const QString& grpName )
{
	for (int i = 0; i < mRootItem->childCount(); ++i)
	{
		if (mRootItem->child(i)->itemName == grpName)
		{
			return index(i, 0);
		}
	}
	return QModelIndex();
}
